local Msg = require("core.Msg")
local MakeTencentCommonParam = require("tencentApi.Define").MakeTencentCommonParam
local Split = require("tencentApi.Define").Split
local Human = require("core.Human")
local DeliverDefine = require("tencentApi.Define")
local Log = require("common.Log")
local Broadcast = require("broadcast.Broadcast")
local Lang = require("common.Lang")
local PfLogic = require("tencentApi.PfLogic")
local ItemDefine = require("bag.ItemDefine")
local Grid = require("bag.Grid")
local AdminPayLogic = require("admin.PayLogicW")
local Config = require("Config")
Json = Json or require("common.Json")
local OperateActLogicW = require("activity.operate.OperateActLogicW")
local RankHandlerW = require("rank.HandlerW")
local FamilyManager = require("family.FamilyManager")
local VipLevel = require("vip.VipLevel")

-- 定义交易表格
TransactionTable = TransactionTable or {}
--用于服务端调用管理后台接口的参数
local s2aParam = {}
-- 交易超时
local kTransactionTimeout = 15 * 60


local function AddTransaction(token, transaction)
    if token == nil or (TransactionTable[token] ~= nil) then
        return false
    end
    TransactionTable[token] = transaction
    return true
end

-- 腾讯发货回调返回码
local kTencentDeliverRetSuccess         = 0
--local kTencentDeliverRetBusy            = 1
--local kTencentDeliverRetTokenTimeout    = 3
local kTencentDeliverRetTokenNotExists  = 3
local kTencentDeliverRetParamError      = 4
local kTencentDeliverRetUserOffline     = 5
local kTencentDeliverRetHandlerFailed   = 6

-- 订单状态
local kTransactionStatusInit    = 1 -- 当腾讯返回token号时，创建交易时的状态
local kTransactionStatusDeliver = 2 -- 当腾讯回调发货成功时，成功发货后的状态
local kTransactionStatusError   = 3 -- 交易出错

local function GetTransaction(token)
    return TransactionTable[token]
end

local function RemoveTransaction(token)
    local transaction = TransactionTable[token]
    TransactionTable[token] = nil
    return transaction
end

local function NewTransaction(token, human_name, deliver_id, deliver_params)
    return {deliver_id = deliver_id, --deliver_id,
            deliver_params = deliver_params,
            token = token,
            timeout = os.time() + kTransactionTimeout,
            status = kTransactionStatusInit, 
            human_name = human_name}
end

local function TransactionDeliver(transaction)
    if (transaction.status ~= kTransactionStatusInit) then
        print("Transaction status error, forcing to deliver status")
    end
    transaction.status = kTransactionStatusDeliver
end

local function TransactionError(transaction)
    transaction.status = kTransactionStatusError
end

local function TransactionConfirmDeliver(token, deliver_result, confirm_param)

    s2aParam = {}

    local callback_general_param = {}
    s2aParam.callback_general_param = callback_general_param
    
    s2aParam.api_url = "/v3/pay/confirm_delivery"
    s2aParam.api_cbMethod = ""


   -- print("TransactionConfirmDeliver:", token)
    if (deliver_result == kTencentDeliverRetSuccess) then
        -- 1. 调用confirm deliver 
        confirm_param.ts = os.time()
        s2aParam.api_param = confirm_param
        s2aParam.userip = confirm_param.userip
        s2aParam.worldid = confirm_param.worldid
        s2aParam.callback_general_param.level = confirm_param.level
        s2aParam.callback_general_param.x5sig = confirm_param.x5sig
        s2aParam.callback_general_param.gold =  confirm_param.gold or 0

        _G.thread_http.send(DeliverDefine.DELIVER_PHP,Json.Encode(s2aParam))
    end
    -- 2.移除Transaction
    RemoveTransaction(token)
end

local function TransactionTimeout(token)
    local transaction = RemoveTransaction(token)
    return transaction
end

-- 后台回调
function OnTencentDeliverReturn(token, billno, payitem, zoneid, amt, payamt_coins,ts,acct)
    -- 标记交易已经发货
    local transaction = GetTransaction(token)
    if (transaction == nil) then
        return {ret=kTencentDeliverRetTokenNotExists, msg="Token not exists."}
    end
    if transaction.status == kTransactionStatusDeliver then
         Update()  
         return {ret=kTencentDeliverRetSuccess, msg="OK"}
    end
    local human_name = transaction.human_name
    local human = Human.onlineHuman[human_name]
    if (human == nil) then
        TransactionError(transaction)
        return {ret=kTencentDeliverRetUserOffline, msg="User not online."}
    end
 
    local deliver_id = transaction.deliver_id
    assert(deliver_id ~= nil)

    local deliver_params = transaction.deliver_params
    if deliver_params == nil then
      deliver_params = {}
    end

    local pf_info = human.pf_info

    -- TODO amt最好还是不要放在deliver_params中，直接作为发货回调的参数
    -- 不要直接修改玩家的回调参数，这样的模式不好，下次要增加参数的时候，一齐修改
    deliver_params.amt = tonumber(amt)
    deliver_params.payamt_coins = tonumber(payamt_coins)
    deliver_params.acct_payamt_coins = acct == "" and 0 or tonumber(acct)
    local itemInfo = Split(payitem, "*")
    if itemInfo then
    deliver_params.item_id = tonumber(itemInfo[1]) or deliver_params.item_id
    deliver_params.price = tonumber(itemInfo[2]) or deliver_params.price
    deliver_params.item_cnt = tonumber(itemInfo[3]) or deliver_params.item_cnt
    end 
    
    transaction.confirm_delivery_params = transaction.confirm_delivery_params or {}
    
    transaction.confirm_delivery_params["openid"] = pf_info.openid
    transaction.confirm_delivery_params["openkey"] = pf_info.openkey
    transaction.confirm_delivery_params["pfkey"] = pf_info.pfkey
    transaction.confirm_delivery_params["pf"] = pf_info.pf
    transaction.confirm_delivery_params["billno"] = billno
    transaction.confirm_delivery_params["payitem"] = payitem
    transaction.confirm_delivery_params["zoneid"] = zoneid
    transaction.confirm_delivery_params["amt"] = amt
    transaction.confirm_delivery_params["payamt_coins"] = payamt_coins
    transaction.confirm_delivery_params["token_id"] = token
    transaction.confirm_delivery_params["provide_errno"] = 0
    transaction.confirm_delivery_params["userip"] = human.ip
    transaction.confirm_delivery_params["worldid"] = pf_info.serverid
    transaction.confirm_delivery_params["level"] = human.db.lv
    transaction.confirm_delivery_params["x5sig"] = pf_info.x5sig
    
    
    transaction.deliver_result = kTencentDeliverRetSuccess
    
    local price = 10
    if deliver_params.item_id == ItemDefine.ITEM_ID_LOTTERY then
        --彩票购买成功：
        if OperateActLogicW.buyLottery(human) == true then
          transaction.confirm_delivery_params["gold"] = 30
        end
        TransactionDeliver(transaction)
    elseif deliver_params.item_id == ItemDefine.ITEM_ID_GOLD_MONTH_CARD then
        VipLevel.buyMonthCard(human, deliver_params.item_cnt)
    elseif deliver_params.item_id == ItemDefine.ITEM_ID_DAILY_GIFT then
        transaction.confirm_delivery_params["gold"] = 30
        OperateActLogicW.buyDailyGift(human)
        TransactionDeliver(transaction)
    else
      local common = ItemDefine.getValue(deliver_params.item_id, "command")
      if not common or not common[2] or common[1] ~= "yuanbao" then
        TransactionError(transaction)
        return {ret=kTencentDeliverRetHandlerFailed, msg="Deliver failed"}
      end  
      TransactionDeliver(transaction)
      price = common[2] 
      local a = deliver_params.acct_payamt_coins or 0
      a = deliver_params.amt + a*10
      AdminPayLogic.pay(human.account, billno, a, deliver_params.item_cnt*common[2], os.time())
      
      transaction.confirm_delivery_params["gold"] = deliver_params.item_cnt*common[2]
    end
    
    
    Update()  
    Log.write(Log.LOGID_OSS_BUYGOOD, human._id, human.account, human.name, human.db.lv, deliver_params.item_id,deliver_params.item_cnt,deliver_params.price,payamt_coins or 0,ts,billno,acct or 0,amt or 0, Human.getLoginPf(human),deliver_params.item_cnt*price, human.db.rmb)
    return {ret=kTencentDeliverRetSuccess, msg="OK"}
end

-- human: Human
-- deliver_id: int
-- item_info: table {{itemid, price, amount}, }
-- allow_modify_count: 
-- buy_mode: 1为exchange_goods,不传或者其他参数则为buy_goods
function MakeTransaction(human, deliver_id, name, description, 
                         item_id, price, item_cnt, deliver_params, appmode--, mode,allow_modify_count,icon_mode, icon_param, buy_mode
                         )

    local pf_info = human.pf_info
    if pf_info == nil then
        assert()
    end
    s2aParam = {}
    -- 构造参数
    local callback_general_param = {}
    callback_general_param.account = human.account
    callback_general_param.name = human.name
    callback_general_param.deliver_params = deliver_params
    callback_general_param.deliver_id = deliver_id
    s2aParam.callback_general_param = callback_general_param
    
    local api_param = MakeTencentCommonParam(pf_info)
    api_param.ts = os.time()
    api_param.payitem = string.format("%s*%d*%d", ""..item_id, price, item_cnt)
    api_param.goodsmeta = string.format("%s*%s", name, description)
    api_param.goodsurl = "http://tq.guorangame.com/" .. item_id .. ".png"
    api_param.zoneid = pf_info.zoneid
    if item_id == ItemDefine.ITEM_ID_LOTTERY or item_id == ItemDefine.ITEM_ID_DAILY_GIFT then
        api_param.max_num = 1
    end
    
    
    s2aParam.api_url = "/v3/pay/buy_goods"
    s2aParam.api_cbMethod = "OnTokenReturnForBuyGood"
    --end
    s2aParam.api_param = api_param
    
    _G.thread_http.send(DeliverDefine.DELIVER_PHP,Json.Encode(s2aParam))
end

function OnTokenReturnForBuyGood(result_json)
    local respond = {}
    respond.ret = 0
    respond.msg = "fail"
    local tencent_ret = result_json.tencent_ret
    local general_param = result_json.callback_general_param

    local human_name = general_param.name
    if (human_name == nil) then
        print("Callback param's name should not be null")
        return Json.Encode(respond) 
    end

    local human = Human.onlineHuman[human_name]
    if human == nil or human.fd == nil then
        print("Human offlined")
        return Json.Encode(respond) 
    end
    
    if (tencent_ret.ret ~= 0) then
        print("Transaction failed, ret:", tencent_ret.ret, " msg:", tencent_ret.msg)
       --OPENKEY过期。 
        if tencent_ret.ret == 1002 then
           Broadcast.sendBroadcast(human,Lang.MOUSE,"登录状态超时，请刷新游戏后再次尝试")
        end
        return Json.Encode(respond)
    end

    assert(general_param.deliver_id ~= nil)
    local deliver_id = general_param.deliver_id
    local token = tencent_ret.token
    local url_params = tencent_ret.url_params
    -- 由于需要保存发货回调等信息，因此在这里建立交易记录，
    -- 提供发货时候提取其中的信息。

    local transaction = NewTransaction(token, human_name, 
                                       deliver_id, general_param.deliver_params)
    local ret = AddTransaction(token, transaction) 
    if (ret == false) then
        print("AddTransaction fail")
        return 
    end
    local msg_ret = Msg.gc.GC_BUY_GOOD_TOKEN
    msg_ret.token = token
    msg_ret.url_params = url_params
    Msg.send(msg_ret, human.fd)
end


local function UpdateEachTransaction(now, token, trans_v)
    if (trans_v.status == kTransactionStatusDeliver) then
        TransactionConfirmDeliver(token, trans_v.deliver_result, 
                                  trans_v.confirm_delivery_params)
        return
    elseif (trans_v.status == kTransactionStatusError) then
        RemoveTransaction(token)
    elseif (trans_v.status == kTransactionStatusInit and 
        now > trans_v.timeout) then
        TransactionTimeout(token)
        return
    end
end

function Update()
    local now = os.time()
    for token, trans_v in pairs(TransactionTable) do
        UpdateEachTransaction(now, token, trans_v)
    end
end

function checkIsLogin()
  local now = os.time()
  local counter = 0
  for account, human in pairs(Human.onlineAccount) do
    if human.pf_info and (human.pf_info.tcTime == nil or human.pf_info.tcTime + 5400 < now) then
      human.pf_info.tcTime = now
      counter = counter + 1
       -- 构造参数
      local callback_general_param = {}
      callback_general_param.account = human.account
      callback_general_param.name = human.name
      s2aParam.callback_general_param = callback_general_param

      local api_param = MakeTencentCommonParam(human.pf_info)       
      s2aParam.api_param = api_param
        
      s2aParam.api_url = "/v3/user/is_login"
      s2aParam.api_cbMethod = "noMethod"
      _G.thread_http.send(DeliverDefine.DELIVER_PHP,Json.Encode(s2aParam))
    end
  end
end



function updateTotalVipInfo(human,blue_vip)
    if not human then return end
    local pf_info = human.pf_info
    if (pf_info == nil) then
        return
    end
    if not PfLogic.isBlueShow(human) then
        return
    end
   -- 构造参数
    local callback_general_param = {}
    callback_general_param.account = human.account
    callback_general_param.name = human.name
    s2aParam.callback_general_param = callback_general_param

    local api_param = MakeTencentCommonParam(pf_info)
    api_param.blue_vip = blue_vip    
    s2aParam.api_param = api_param
    
    s2aParam.api_url = "/v3/user/total_vip_info"
    s2aParam.api_cbMethod = "OnTotalVipInfoReturn"
    _G.thread_http.send(DeliverDefine.DELIVER_PHP,Json.Encode(s2aParam))
end

function OnTotalVipInfoReturn(result_json)
    local respond = {}
    respond.ret = 0
    respond.msg = "fail"
    
    local tencent_ret = result_json.tencent_ret
    local general_param = result_json.callback_general_param
    
    local human_name = general_param.name
    if (human_name == nil) then
        print("Callback param's name should not be null")
        return Json.Encode(respond)
    end

    local human = Human.onlineHuman[human_name]
    if human == nil or not human.fd then
        print("Human offlined")
        return  Json.Encode(respond)
    end
    
    if (tencent_ret.ret ~= 0) then
        print("Transaction failed, ret:", tencent_ret.ret, " msg:", tencent_ret.msg)
       --OPENKEY过期。 
        if tencent_ret.ret == 1002 then
         Broadcast.sendBroadcast(human,Lang.MOUSE,"登录状态超时，请刷新游戏后再次尝试")
        end
        return Json.Encode(respond)
    end
    
    respond.ret = 1
    respond.msg = "success"
    local change
    tencent_ret.is_high_blue = tencent_ret.is_high_blue or 0
    if human.db.blueVip ~= tencent_ret.is_blue or 
        human.db.blueVipLv ~= tencent_ret.blue_level or
        human.db.blueYearVip ~= tencent_ret.is_year_blue or 
        human.db.blueSuperVip ~= tencent_ret.is_high_blue then
       
        human.db.blueVip = tencent_ret.is_blue 
        human.db.blueVipLv = tencent_ret.blue_level 
        human.db.blueYearVip = tencent_ret.is_year_blue
        human.db.blueSuperVip = tencent_ret.is_high_blue

        if PfLogic.isBlueShow(human) then
          --刷新客户端蓝钻信息。
          Human.sendBlueInfo(human)
        end
        RankHandlerW.allChange(human)
        FamilyManager.changeBlue(human)
        Log.write(Log.LOGID_OSS_OPENVIP, human._id, human.account, human.name, human.db.lv, human.db.blueVip, human.db.blueVipLv,human.db.blueYearVip,human.db.blueSuperVip)      
    end    
    return  Json.Encode(respond)  
end

function onLianyunPay(account, order, rmb, yb, ts, gm)
 local result = AdminPayLogic.pay(account, order, rmb, yb, ts, gm)
 if result == AdminPayLogic.PAY_ERR_OK then
     local human = Human.onlineAccount[account]
     if human then
        OperateActLogicW.buyDailyGift(human)
     end
    return 1,"pay ok"
  elseif result == AdminPayLogic.PAY_ERR_REPEAT_ORDER then
    return 4, "order " .. order .. " exist"
  else
    return 2,"account " ..  account .. " not exist"
  end
end